﻿#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "priority_queue.h"
#define LOG_ERR printf
#define LOG_DBG printf


priority_queue_t *priority_queue_init(void)
{
    priority_queue_t *queue = (priority_queue_t *) malloc( sizeof(priority_queue_t) );
    if ( queue != NULL )
    {
        memset( queue, 0, sizeof(priority_queue_t) );
        queue->front		= NULL;
        queue->size		= 0;
        if ( pthread_mutex_init( &queue->mutex, NULL ) < 0)
        {
            LOG_ERR( "%s(%d) pthread_mutex_init error\n" , __FUNCTION__, __LINE__);
            free( queue ); /* 释放申请到的资源 */
            return(NULL);
        }
    }
    return(queue);
}


void priority_queue_deinit( priority_queue_t *queue )
{
    if ( !queue )
    {
        LOG_ERR( "%s(%d) queue is NULL\n" , __FUNCTION__, __LINE__);
        return;
    }

    if(pthread_mutex_destroy( &(queue->mutex) ) < 0)
    {
        LOG_ERR( "%s(%d) pthread_mutex_destroy error\n" , __FUNCTION__, __LINE__);
    }
    free( queue );
}


static void priority_queue_adjust( priority_queue_t *queue, link_node_t *new_node )
{
    link_node_t	*pre_node	= NULL;
    link_node_t	*cur_node	= queue->front;
    while ( NULL != cur_node )
    {
//        if ( (queue->sortCallBack != NULL)
//             && (1 == queue->sortCallBack( cur_node->item, new_node->item ) ) ) /* 由回调函数来决定 */
//        {
//            break;
//        }
        pre_node = cur_node;
        cur_node = cur_node->link;
    }

    if ( pre_node == NULL )
    {
        new_node->link	= cur_node;
        queue->front	= new_node;
    }
    else
    {
        pre_node->link	= new_node;
        new_node->link	= cur_node;
    }
}


void* priority_queue_get_head( priority_queue_t *queue )        /* 读取队头(具最小优先权)的值 */
{
    void *item;

    pthread_mutex_lock( &queue->mutex );
    if ( NULL == queue->front )
    {
        pthread_mutex_unlock( &queue->mutex );
        return(NULL);
    }
    item = queue->front->item;
    pthread_mutex_unlock( &queue->mutex );

    return(item);
}


int priority_queue_push( priority_queue_t *queue, void *item )      /* 将新元素x插入到队尾 */
{
    link_node_t *new_node = malloc( sizeof(link_node_t) );
    if ( !new_node )
    {
        LOG_ERR( "ctCalloc  new_node failed\n" );
        return(-1);
    }
    new_node->item	= item;
    new_node->link	= NULL;

    pthread_mutex_lock( &queue->mutex );

    if ( NULL == queue->front )
    {
        queue->front = new_node;
        queue->size++;
        pthread_mutex_unlock( &queue->mutex );

        return(0);
    }
    priority_queue_adjust( queue, new_node );
    queue->size++;
    pthread_mutex_unlock( &queue->mutex );


    return(0);
}


void *priority_queue_pop_head( priority_queue_t *queue )           /* 将队头元素删除 */
{
    void *item;

    pthread_mutex_lock( &queue->mutex );

    link_node_t *cur_node = queue->front;
    if ( NULL == cur_node )
    {
        pthread_mutex_unlock( &queue->mutex );
        return(NULL);
    }

    queue->front	= queue->front->link;
    item		= cur_node->item;
    free( cur_node );
    queue->size--;

    pthread_mutex_unlock( &queue->mutex );

    return(item);
}


int priority_queue_is_empty( priority_queue_t *queue )           /* 判断队列是否为空 */
{
    int ret = 0;
    pthread_mutex_lock( &queue->mutex );
    ret = (NULL == queue->front) ? 1 : 0;
    pthread_mutex_unlock( &queue->mutex );
    return(ret);
}


int priority_queue_size( priority_queue_t *queue )            /* 求优先级队列中元素个数 */
{
    int size = 0;

    pthread_mutex_lock( &queue->mutex );
    size = queue->size;

    pthread_mutex_unlock( &queue->mutex );

    return(size);
}

int priority_queue_delete_item( priority_queue_t *queue, void *spec_item )
{
    pthread_mutex_lock( &queue->mutex );
    void *item = NULL;
    link_node_t	*front	= queue->front;
    link_node_t	*temp	= NULL;

    if ( front == NULL )
    {
        pthread_mutex_unlock( &queue->mutex );
        return(-1);
    }

    if ( front->item == spec_item )
    {
        queue->size--;
        item		= front->item;
        queue->front	= front->link;
        free( front );
        pthread_mutex_unlock( &queue->mutex );
        return(0);
    }
    else
    {
        while ( front != NULL )
        {
            temp	= front;
            front	= front->link;
            if ( NULL == front )
            {
                pthread_mutex_unlock( &queue->mutex );
                return(-1);
            }
            else if ( front->item == spec_item )    /*找到data值为num的结点*/
            {
                queue->size--;
                item		= front->item;
                temp->link	= front->link;      /*elem前一个结点的next指向elem元素后一个结点*/
                free( front );                  /*释放被删除的结点占用的空间*/
                break;
            }
        }
    }

    pthread_mutex_unlock( &queue->mutex );

    return(0);
}

void priority_queue_traverse( priority_queue_t *queue, void *user_data, void (*traverseCallBack)( void *srcItem, void *user_data ) )
{
    pthread_mutex_lock( &queue->mutex );
    link_node_t *front = NULL;

    for ( front = queue->front; front != NULL; front = front->link )
    {
        if ( traverseCallBack )
            traverseCallBack( front->item, user_data );
    }
    pthread_mutex_unlock( &queue->mutex );
}


int priority_queue_find( priority_queue_t *queue, void *dstItem )
{
    int ret = 0;

    pthread_mutex_lock( &queue->mutex );

    link_node_t *front = NULL;

    for ( front = queue->front; front != NULL; front = front->link )
    {
        if ( front->item == dstItem )
        {
            ret = 1;
            break;
        }
    }

    pthread_mutex_unlock( &queue->mutex );

    return(ret);
}


